#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "shmem.h"
#include "cJSON.h"
#include "msg_queue_peer.h"
#include <unistd.h>
union val_t
{
    int b_val;
    int i_val;
    float f_val;
};
struct std_node
{
    int key;
    int type;
    int dev_type;
    union val_t old_val;
    union val_t new_val;
    int ret;
};
struct msgbuf
{
    long type;
    int key;
    union val_t val;
};
fd_set readfds, tempfds;
static struct shm_param shm;
static int *total;                // 指向共享内存中数据节点总个数
static struct std_node *node_arr; // 指向共享内存中节点缓存数组头
#define MAX_NODE 128              // 最大支持学生数目，实际可用是127
#define STD_NODE_LEN sizeof(struct std_node)
#define MAX_NODE_SIZE 1024
char buf[1024] = {"wuhuqifei"};
char rev_buf[1024] = {0};
char send_buf[1024] = {0};
pthread_t tid2;
int Send_Signal = 0;
int max = 0;
pthread_mutex_t lock;
cJSON *data_object = NULL;
struct msgbuf recv_buf;
int mask = 0;

void *Recv_Queue(void *arg)
{
    while (1)
    {
        if (msg_queue_recv("msg", &recv_buf, sizeof(recv_buf), 0, 0) > 0)
        {
            printf("%d %d %ld\n", recv_buf.key, recv_buf.val.b_val,recv_buf.type);
            if (recv_buf.type == 111 || recv_buf.type == 2)
            {
                sprintf(send_buf,"key=%d,val=%d", recv_buf.key, recv_buf.val.b_val);
                printf("=================================%s\n", send_buf);
            }
        }
        else
        {
            perror("recv error:");
            return NULL;
        }
        for (int i = 4; i <= max; i++)
        {
            if (Send_Signal == 0)
            {
                sleep(1);
                Send_Signal = 1;
            }
            if (Send_Signal == 1)
            {
                if (FD_ISSET(i, &readfds))
                {
                    printf("%s\n",send_buf);
                    send(i, &send_buf, sizeof(send_buf), 0);
                }
            }
        }
        sleep(1);
    }

    // return NULL;
}
void *shareInput(void *arg)
{
    int ret = -1;
    ret = shm_init(&shm, "shm", MAX_NODE_SIZE);
    if (ret < 0)
    {
        perror("shm_init error ");
    }
    void *node_p = shm_getaddr(&shm);
    if (node_p == NULL)
    {
        perror("shm_getaddr err");
    }
    memset(node_p, 0, MAX_NODE_SIZE);
    total = (int *)node_p;
    node_arr = (struct std_node *)(node_p + sizeof(int));
    while (1)
    {
        printf("%s\n", rev_buf);
        cJSON *root = cJSON_Parse(rev_buf);
        if (NULL == root)
        {
            perror("format ERROR ");
            return NULL;
        }
        cJSON *data_array = cJSON_GetObjectItem(root, "data");
        if (NULL == data_array)
        {
            printf("Error: 'data' is not an array\n");
            cJSON_Delete(root);
            return NULL;
        }
        int data_array_size = cJSON_GetArraySize(data_array);
        *total =13;
        for (int i = 0; i < data_array_size; i++)
        {
            data_object = cJSON_GetArrayItem(data_array, i);
            if (NULL == data_object)
            {
                perror("data_object error");
            }
            node_arr[i].key = cJSON_GetObjectItem(data_object, "key")->valueint;
            node_arr[i].type = cJSON_GetObjectItem(data_object, "type")->valueint;
            if (node_arr[i].type == 2)
            {
                node_arr[i].new_val.i_val = cJSON_GetObjectItem(data_object, "value")->valueint;
            }
            else if (node_arr[i].type == 3)
            {
                // printf("--------------------%d\n", __LINE__);
                node_arr[i].new_val.f_val = (float)atof(cJSON_GetObjectItem(data_object, "value")->valuestring);
                // printf("key=%d ,  type =%d, value =%.2f\n", node_arr[i].key, node_arr[i].type, node_arr[i].new_val.f_val);
            }
            else if (node_arr[i].type == 1)
            {
                node_arr[i].new_val.b_val = atoi(cJSON_GetObjectItem(data_object, "value")->valuestring);
                // printf("key=%d ,  type =%d, value =%d\n", node_arr[i].key, node_arr[i].type, node_arr[i].new_val.b_val);
            }
        }
        // for (int i = 0; i < *total; i++)
        // {
        //     printf("================================\n");
        //     printf("key=%d\n", node_arr[i].key);
        //     printf("val=%d\n", node_arr[i].new_val.i_val);
        //     printf("================================\n");
        // }
        sleep(1);
    }
}
int main(int argc, char const *argv[])
{
    pthread_t tid;
    int va12 = 1;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("sockfd err");
    }
    struct sockaddr_in caddr;
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[2]));
    saddr.sin_addr.s_addr = INADDR_ANY;
    socklen_t addrlen = sizeof(saddr);
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &va12, 4))
    {
        perror("setsock err.");
        return -1;
    }
    if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("bind err");
        return -1;
    }
    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    if (argc != 3)
    {
        printf("usage:<ip> <port>\n");
        return -1;
    }

    FD_ZERO(&readfds);
    FD_SET(0, &readfds);
    FD_SET(sockfd, &readfds);
    max = sockfd;
    if (pthread_create(&tid2, NULL, Recv_Queue, NULL) != 0)
    {
        perror("create Recv_Queue Error");
    };
    while (1)
    {
        tempfds = readfds;
        select(max + 1, &tempfds, NULL, NULL, NULL);
        if (FD_ISSET(sockfd, &tempfds))
        {
            int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &addrlen);
            if (acceptfd < 0)
            {
                perror("acceptfd err");
                return -1;
            }
            FD_SET(acceptfd, &readfds);
            if (max < acceptfd)
            {
                max = acceptfd;
            }
            printf("conncet ok\n");
            printf("acceptfd:%d\n", acceptfd);
            printf("ip:%s port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
        }
        // if(FD_ISSET(0,&tempfds)){
        //  memset(buf,0,sizeof(buf));
        //  gets(buf);

        for (int i = 4; i <= max; i++)
        {
            if (FD_ISSET(i, &tempfds))
            {
                int ret = recv(i, rev_buf, sizeof(rev_buf), 0);
                if (ret < 0)
                {
                    perror("recv error");
                }
                else if (ret > 0)
                {
                    if (mask == 0)
                    {
                        if (pthread_create(&tid, NULL, shareInput, NULL) == 0)
                        {
                            mask = 1;
                        }
                        else
                        {
                            perror("create thread err");
                            return -1;
                        }
                    }
                }
                else
                {

                    printf("%d:quit", i);
                    close(i);
                    FD_CLR(i, &readfds);
                    while (!FD_ISSET(max, &readfds))
                    {
                        max--;
                    }
                }
            }
        }
    }
    return 0;
}